package com.texaco.chapasFutbol.multiplayer;

import java.io.IOException;

import org.andengine.util.debug.Debug;
import org.json.JSONException;

import com.texaco.chapasFutbol.entidades.Game;
import com.texaco.chapasFutbol.multiplayer.mensajes.AckMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.BaseMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.GoalMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.IMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.MatchMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.PositionsMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.QuitMatchMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.ResumeMatchMessage;
import com.texaco.chapasFutbol.multiplayer.mensajes.ShootMessage;

public class Multiplayer {

	private int orderMessage = 1;
	private int orderRecived = 0;
	private long idClient;
	private long idMatch;
	private String team;
	private boolean running = false;
	private int countDown = 5;
	private Game game;
	Object lock = new Object();

	
	public Multiplayer(Game game){
		super();
		/*
		 * Establecemos la menor prioridad 
		 * posible con la idea de que no deje 
		 * tostados los dispositivos durante la consulta al server.
		 */
		workingThread.setPriority(Thread.MIN_PRIORITY);
//		workingThread.setDaemon(true);
		workingThread.start();
		this.game = game;
	}
	
	final Thread workingThread = new Thread(new Runnable() {
		public void run() {
			boolean updated = false;
			int sleep = 500;
			int failed = 0;
			int maxFailed = 10;
			BaseMessage serverMessage;
			while (true){
				while (running) {
					try {
						synchronized (lock) {
							serverMessage = ServerUtilities.callRequestUpdate(getIdClient(), getOrderRecived());
							updated = !(serverMessage instanceof AckMessage);
							if (!updated) {
								if (failed < maxFailed) {
									failed++;
								}
							} else {
								setOrderRecived(serverMessage.getOrder() + 1);
								failed = 0;
							}
						}
						if(updated){
							processMessage(serverMessage);
						}
						Thread.sleep(sleep * failed);
						System.out.println("Sleep: " + (sleep * failed));
					} catch (JSONException e) {
						Debug.d("Error de json: " + e.getCause() + " " + e.getMessage());
					} catch (final InterruptedException e) {
						game.getActivity().runOnUpdateThread(new Runnable() {
							public void run() {
								game.onMultiplayerError(e);

							}
						});
					} catch (final IOException e) {
						game.getActivity().runOnUpdateThread(new Runnable() {
							public void run() {
								game.onMultiplayerError(e);
							}
						});
					}
				}
				
				if(!running){
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						game.onMultiplayerError(e);
					}
				}
				
			}
		}
	});
	
	private void processMessage(BaseMessage serverMessage) {
		if(serverMessage instanceof MatchMessage){
			final MatchMessage matchMessage = (MatchMessage) serverMessage;
//			idClient = matchMessage.getIdClient();
			game.getActivity().runOnUpdateThread(new Runnable() {
				public void run() {
					setIdMatch(matchMessage.getIdMatch());
					setTeam(matchMessage.getTeam());
					game.beforeMultiplayerMatch();
				}
			});
		}else if(serverMessage instanceof ShootMessage){
			final ShootMessage shootMessage = (ShootMessage) serverMessage;
			game.getActivity().runOnUpdateThread(new Runnable() {
				public void run() {
					game.moverChapa(shootMessage.getIdChapa(), shootMessage.getX(), shootMessage.getY());
					}
				});
		}else if(serverMessage instanceof ResumeMatchMessage){
			game.getActivity().runOnUpdateThread(new Runnable() {
				public void run() {
					game.reanudarJuego();
				}
			});
		}else if(serverMessage instanceof QuitMatchMessage){
			game.getActivity().runOnUpdateThread(new Runnable() {
				public void run() {
					game.rivalAbandona();
				}
			});
		}else if(serverMessage instanceof GoalMessage){
			final GoalMessage goalMsg = (GoalMessage) serverMessage;
			game.getActivity().runOnUpdateThread(new Runnable() {
				public void run() {
					game.onRemoteGoal(goalMsg.getTeam());
				}
			});
		}else if(serverMessage instanceof PositionsMessage){
			final PositionsMessage posMsg = (PositionsMessage) serverMessage;
			game.getActivity().runOnUpdateThread(new Runnable() {
				public void run() {
					game.updateCapsPos(posMsg.getCapsLPos(), 
							posMsg.getBallPos().get(0).floatValue(), 
							posMsg.getBallPos().get(1).floatValue());
				}
			});
		}
	}

	public void startClient() {
		synchronized (lock) {
			running = true;
		}
	}

	public void stopClient() {
		running = false;
	}
	
	public boolean isLocal(){
		return team.equals(IMessage.LOCAL_TEAM);
	}
	
	public boolean isVisitante(){
		return team.equals(IMessage.VISIT_TEAM);
	}

	public long getIdClient() {
		return idClient;
	}

	public synchronized void setIdClient(long idClient) {
		this.idClient = idClient;
	}

	public long getIdMatch() {
		return idMatch;
	}

	public synchronized void setIdMatch(long idMatch) {
		this.idMatch = idMatch;
	}

	public String getTeam() {
		return team;
	}

	public synchronized void setTeam(String team) {
		this.team = team;
	}

	public int updateCountDown() {
		return --countDown;
	}

	public void resetTimeCountDown() {
		countDown = 5;
	}

	public int getOrderMessage() {
		return orderMessage++;
	}

	public void setOrderMessage(int orderMessage) {
		this.orderMessage = orderMessage;
	}
	
	public void resetOrderMessages(){
		this.orderMessage = 1;
	}

	public int getOrderRecived() {
		return orderRecived;
	}

	public void setOrderRecived(int orderRecived) {
		this.orderRecived = orderRecived;
	}
	
	public void resetOrderRecived(){
		this.orderRecived = 0;
	}

	public void resetAndStop() {
		Debug.d("THREADING - Se para el demonio y reinicia el multiplayer");
		synchronized (lock) {
			stopClient();
			resetOrderMessages();
			resetOrderRecived();
		}
	}
}
